package priv.tuyou.bo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import priv.tuyou.bo.SqlParam.Condition;

/**
 * 参数组（相当于用括号括起来的一组参数）
 * @author 涂有
 */
public class SqlParamGroup {
	
	/**
	 * 添加条件类型
	 */
	public static enum Logic{
		and,
		or
	}

	/**
	 * 所有参数的集合
	 */
	protected List<Object> conditions = new ArrayList<Object>();
	
	/**
	 * 参数的拼接的逻辑条件
	 */
	protected List<Logic> logics = new ArrayList<Logic>();
	
	/**
	 * 是否已经生成
	 */
	private boolean generated;
	
	/**
	 * 生成的sql
	 */
	private String sql;
	
	/**
	 * 获取参数的键值对
	 */
	private Map<String, Object> params = new HashMap<String, Object>();
	
	/**
	 * 初始化的时候必须传入一个参数
	 * @param param
	 */
	public SqlParamGroup(SqlParam param) {
		
		this.conditions.add(param);
	}
	
	/**
	 * 初始化的时候必须传入一个参数
	 * @param field 字段名
	 * @param condition 比较条件
	 * @param param 参数值
	 */
	public SqlParamGroup(String field, Condition condition) {
		
		this.conditions.add(new SqlParam(field, condition));
	}
	
	/**
	 * 初始化的时候必须传入一个参数
	 * @param field 字段名
	 * @param condition 比较条件
	 * @param param 参数值
	 */
	public SqlParamGroup(String field, Condition condition, Object value) {
		
		this.conditions.add(new SqlParam(field, condition, value));
	}
	
	/**
	 * 初始化的时候必须传入一个参数
	 * @param field 字段名
	 * @param condition 比较条件
	 * @param param 参数值
	 */
	public SqlParamGroup(String field, Condition condition, Object value, Object value2) {
		
		this.conditions.add(new SqlParam(field, condition, value, value2));
	}
	
	/**
	 * 逻辑与操作
	 * @param field
	 * @param condition
	 * @param value
	 * @return
	 */
	public SqlParamGroup and(String field, Condition condition){
		
		return and(new SqlParam(field, condition));
	}
	
	/**
	 * 逻辑与操作
	 * @param field
	 * @param condition
	 * @param value
	 * @return
	 */
	public SqlParamGroup and(String field, Condition condition, Object value){
		
		return and(new SqlParam(field, condition, value));
	}
	
	/**
	 * 逻辑与操作
	 * @param field
	 * @param condition
	 * @param value
	 * @return
	 */
	public SqlParamGroup and(String field, Condition condition, Object value, Object value2){
		
		return and(new SqlParam(field, condition, value, value2));
	}
	
	/**
	 * 逻辑与一个条件
	 * @param param
	 * @return
	 */
	public SqlParamGroup and(SqlParam param){
		
		this.conditions.add(param);
		this.logics.add(Logic.and);
		return this;
	}
	
	/**
	 * 逻辑与一个条件组
	 * @param param
	 * @return
	 */
	public SqlParamGroup and(SqlParamGroup group){
		
		this.conditions.add(group);
		this.logics.add(Logic.and);
		return this;
	}
	
	/**
	 * 逻辑或一个条件
	 * @param field
	 * @param condition
	 * @param value
	 * @return
	 */
	public SqlParamGroup or(String field, Condition condition){
		
		return or(new SqlParam(field, condition));
	}
	
	/**
	 * 逻辑或一个条件
	 * @param field
	 * @param condition
	 * @param value
	 * @return
	 */
	public SqlParamGroup or(String field, Condition condition, Object value){
		
		return or(new SqlParam(field, condition, value));
	}
	
	/**
	 * 逻辑或一个条件
	 * @param field
	 * @param condition
	 * @param value
	 * @return
	 */
	public SqlParamGroup or(String field, Condition condition, Object value, Object value2){
		
		return or(new SqlParam(field, condition, value, value2));
	}
	
	/**
	 * 逻辑或一个条件
	 * @param param
	 * @return
	 */
	public SqlParamGroup or(SqlParam param){
		
		this.conditions.add(param);
		this.logics.add(Logic.or);
		return this;
	}
	
	/**
	 * 逻辑或一个条件组
	 * @param param
	 * @return
	 */
	public SqlParamGroup or(SqlParamGroup group){
		
		this.conditions.add(group);
		this.logics.add(Logic.or);
		return this;
	}
	
	/**
	 * 生成
	 * @author：涂有
	 * @date 2017年1月1日 下午11:49:52
	 */
	private void generate(){
		
		StringBuilder condition = new StringBuilder();
		for(int i = 0; i < conditions.size(); i++){
			
			Object param = conditions.get(i);
			String sqlItem = param.toString();
			
			if(sqlItem != null && !"".equals(sqlItem.trim())){
				
				if(i > 0 && !"".equals(condition.toString())){
					
					Logic logic = logics.get(i - 1);
					if(logic == Logic.and){
						
						condition.append(" and ");
					}else if(logic == Logic.or){
						
						condition.append(" or ");
					}
				}
				
				if(param instanceof SqlParam){
					
					SqlParam sqlParam = (SqlParam)param;
					sqlItem = putAll(sqlParam.getParamArray(), sqlItem);
					condition.append(sqlItem);
				}else{
					
					SqlParamGroup group = (SqlParamGroup)param;
					sqlItem = putAll(group.getParamArray(), sqlItem);
					condition.append("(").append(sqlItem).append(')');
				}
			}
		}
		generated = true;
		sql = condition.toString();
	}
	
	/**
	 * 拼接成sql字符串
	 */
	public String toString(){
		
		if(!generated){
			
			generate();
		}
		return sql;
	}
	
	/**
	 * 拼接成sql字符串
	 */
	public String toString(boolean addWhere){
		
		String paramsStr = toString();
		if(addWhere){
			
			return paramsStr == null ? "" : "where " + paramsStr;
		}
		return paramsStr;
	}
	
	/**
	 * 得到参数的数组
	 * @return
	 */
	public Map<String, Object> getParamArray(){
		
		if(!generated){
			
			generate();
		}
		return params;
	}
	
	/**
	 * 根据name得到一个新name，也就是后面的数字加1
	 * @author：涂有
	 * @date 2017年1月2日 上午12:18:43
	 * @param name
	 * @return
	 */
	public static String getNewName(String name){

		StringBuilder numberStrBuilder = new StringBuilder();
		int lastIndex = name.length();
		for(int i = name.length()-1; i >= 0; i--){
			
			char c = name.charAt(i);
			if(c >= '0' && c <= '9'){
				
				numberStrBuilder.append(c);
				lastIndex = i;
			}else{
				
				break;
			}
		}
		numberStrBuilder.reverse();
		
		int number = 1;
		if(numberStrBuilder.length() > 0){
			
			number = Integer.parseInt(numberStrBuilder.toString()) + 1;
		}
		
		String originalName = name.substring(0, lastIndex);
		String numberStr = numberStrBuilder.toString();
		if(numberStr.startsWith("0")){
			
			return originalName + "0" + number;
		}
		return originalName + number;
	}
	
	/**
	 * 
	 * @author：涂有
	 * @date 2017年1月2日 上午12:19:41
	 * @param map
	 */
	public String putAll(Map<String, Object> map, String sqlItem){
		
		for(String name : map.keySet()){
			
			String newName = name;
			while(params.get(newName) != null){
				
				String newestName = getNewName(newName);
				sqlItem = sqlItem.replace("#{" + newName + "}", "#{" + newestName + "}");
				newName = newestName;
			}
			params.put(newName, map.get(name));
		}
		
		return sqlItem;
	}
	
	public static void main(String[] args) {
		
		SqlParamGroup group = new SqlParamGroup("name", Condition.like_left, "涂有").and("age", Condition.between, 0, 24);
		SqlParamGroup group2 = new SqlParam("name", Condition.like, "杨瑞").and("age", Condition.between, 5, 44);
		group.or(group2);
		
		System.out.println(group.toString());
		System.out.println(group.getParamArray());
		
//		System.out.println(getNewName("name999"));
//		System.out.println(getNewName("name"));
	}
}
